import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.Random;

/**
 * Created by Brill on 2015/12/30.
 * 贪食蛇游戏核心代码
 */

public class SnakeGame {

    //地图的高和宽
    public static final int WIDTH = 35;
    public static final int HIGTH = 9;

    //用一个二维组保存信息
    char[][] background = new char[HIGTH][WIDTH];

    //用一个集合保存蛇的信息
    LinkedList<Point> snake = new LinkedList<Point>();

    //用point保存食物
    Point food;

    //蛇头的方位
    public static final int UP_DIRECTION = 1;       //上
    public static final int DOWN_DIRECTION = -1;    //下
    public static final int LIFT_DIRECTION = 2;     //左
    public static final int RIGHT_DIRECTION = -2;   //右

    //蛇当前方向
    int currentDirection = -2;  //默认向右走】

    //记录游戏是否结束
    static boolean isGameOver = false; //默认游戏没有结束


    //初始化蛇
    public void initSnake() {
        int x = WIDTH / 2;
        int y = HIGTH / 2;
        snake.addFirst(new Point(x - 1, y));    //尾
        snake.addFirst(new Point(x, y));        //身
        snake.addFirst(new Point(x + 1, y));    //头
    }

    //显示蛇
    public void showSnake() {
        //取出蛇头
        Point head = snake.getFirst();
        background[head.y][head.x] = '$';

        //蛇身
        for (int i = 1; i < snake.size(); i++) {
            Point body = snake.get(i);
            background[body.y][body.x] = '#';
        }
    }

    //蛇移动的方法
    public void move() {
        //取出蛇头
        Point head = snake.getFirst();
        //蛇是根据当前的方向移动的
        switch (currentDirection) {
            case UP_DIRECTION:
                //添加新的蛇头
                snake.addFirst(new Point(head.x, head.y - 1));
                break;
            case DOWN_DIRECTION:
                snake.addFirst(new Point(head.x, head.y + 1));
                break;
            case LIFT_DIRECTION:
                if (head.x == 0) {
                    snake.addFirst(new Point(WIDTH - 1, head.y));
                }else {
                    snake.addFirst(new Point(head.x - 1, head.y));
                }
                break;
            case RIGHT_DIRECTION:
                if (head.x == WIDTH - 1) {
                    snake.addFirst(new Point(0, head.y));
                } else {
                    snake.addFirst(new Point(head.x + 1, head.y));
                }
                break;
            default:
                break;

        }
        if (eat()) {
            creatFood();
        } else {
            snake.removeLast();
        }
    }

    //改变方向
    public void changeDirection(int newDirection) {
        //判断现场的方向与要改变的方面是否一样
        if (newDirection + currentDirection != 0) {
            currentDirection = newDirection;
        }
    }

    //初始化食物
    public void creatFood() {
        Random random = new Random();
        while (true) {
            int x = random.nextInt(WIDTH);
            int y = random.nextInt(HIGTH);
            if (background[y][x] != '*') {
                food = new Point(x, y);
                break;
            }
        }

    }

    //显示食物
    public void showFood() {
        background[food.y][food.x] = '@';
    }

    //吃食物
    public boolean eat() {
        if (snake.getFirst().equals(food)) {
            return true;
        }
        return false;
    }

    //初始化地图，并把地图信息保存在一个二维数组中
    public void initMap() {
        for (int y = 0; y < HIGTH; y++) {
            for (int x = 0; x < WIDTH; x++) {
                if (y == 0 || y == HIGTH - 1 || x == 0 || x == WIDTH - 1) {
                    background[y][x] = '*';
                } else {
                    background[y][x] = ' ';
                }
            }
        }
    }

    //显示地图
    public void showMap() {
        for (int y = 0; y < HIGTH; y++) {
            for (int x = 0; x < WIDTH; x++) {
                System.out.print(background[y][x]);
            }
            System.out.println();
        }
    }

    //刷新游戏的状态
    public void refresh() {
        //重置地图
        initMap();
        //把蛇最新的状态反映在地图上
        showSnake();
        //食物
        showFood();
        //显示地图
        showMap();
    }

    //游戏结束
    public void isGameOver() {
        //撞墙死亡
        Point head = snake.getFirst();
        if (background[head.y][head.x] == '*') {
            isGameOver = true;
        }

        //咬到自己
        for (int i = 1; i < snake.size(); i++) {
            Point point = snake.get(i);
            if (head.equals(point)) {
                isGameOver = true;
            }
        }
    }

    public static void main(String[] args) {
        SnakeGame snake = new SnakeGame();
        snake.initMap();
        snake.initSnake();
        snake.creatFood();
        snake.showSnake();
        snake.showFood();
        snake.showMap();


        //使用图形化介面，添加键盘监听器
        JFrame frame = new JFrame("方向盘");
        frame.add(new JButton("向上"), BorderLayout.NORTH);
        frame.add(new JButton("向下"),BorderLayout.SOUTH);
        frame.add(new JButton("向左"), BorderLayout.WEST);
        frame.add(new JButton("向右"), BorderLayout.EAST);
        JButton button = new JButton("方向控制器");
        frame.add(button);
        FrameUtil.initFrame(frame, 300, 300);
        //给按钮添加事件监听器
        button.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int code = e.getKeyCode();
                switch (code) {
                    case KeyEvent.VK_UP:
                        snake.changeDirection(UP_DIRECTION);
                        break;
                    case KeyEvent.VK_DOWN:
                        snake.changeDirection(DOWN_DIRECTION);
                        break;
                    case KeyEvent.VK_LEFT:
                        snake.changeDirection(LIFT_DIRECTION);
                        break;
                    case KeyEvent.VK_RIGHT:
                        snake.changeDirection(RIGHT_DIRECTION);
                        break;
                    default:
                        break;
                }
                snake.move();
                snake.isGameOver();
                snake.refresh();
                if (isGameOver) {
                    System.out.println("GAME OVER!");
                    System.exit(0);
                }
            }
        });
    }

}
